package com.xinhe.web.session;

import com.xinhe.web.redis.ObjectRedisTemplate;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Component
public class TokenManager {
    private static final Long EXPIRE_TIME = Long.valueOf(604800000L);

    private static final String HEADER_TOKEN_KEY = "x-access-token";

    private static final String REDIS_KEY = "x-access-token";
    private static final String MULTIPLE_SESSION = "ms";
    @Autowired(required = false)
    private HttpServletRequest request;
    @Autowired
    private ObjectRedisTemplate<String, TokenView> redisTemplate;

    public TokenView saveToken(Long userId) {
        TokenView view = new TokenView();
        Long currentTimeMillis = Long.valueOf(System.currentTimeMillis());
        view.setKey(DigestUtils.md5Hex(userId.toString()));
        view.setCreateTime(currentTimeMillis);
        view.setExpireTime(Long.valueOf(currentTimeMillis.longValue() + EXPIRE_TIME.longValue()));
        HashOperations<String, String, TokenView> opsForHash = this.redisTemplate.opsForHash();
        String token = String.format("%s_%s", new Object[] { view.getKey(), view.getCreateTime().toString() });
        view.setToken(token);
        opsForHash.put("x-access-token", view.getKey(), view);
        return view;
    }

    public boolean validToken() {
        String requestTokenStr = getHeader("x-access-token");
        if (StringUtils.isBlank(requestTokenStr)) {
            return false;
        }
        //token:用户id_时间戳。根据客户端传的token，解析出来用户id（也是redis hash中的key），去redis hash中查询是否存在
        String[] requestTokenParts = requestTokenStr.split("_");
        HashOperations<String, String, TokenView> opsForHash = this.redisTemplate.opsForHash();
        TokenView tokenView = (TokenView)opsForHash.get("x-access-token", requestTokenParts[0]);
        if (null == tokenView) {
            return false;
        }
        if (requestTokenParts.length < 2) {
            return false;
        }
        Long currentTimeMillis = Long.valueOf(System.currentTimeMillis());
        if (!"ms".equals(requestTokenParts[1]) && (
                !tokenView.getCreateTime().toString().equals(requestTokenParts[1]) || currentTimeMillis
                        .longValue() > tokenView.getExpireTime().longValue())) {
            return false;
        }
        tokenView.setExpireTime(Long.valueOf(currentTimeMillis.longValue() + EXPIRE_TIME.longValue()));
        opsForHash.put("x-access-token", tokenView.getKey(), tokenView);
        return true;
    }


    public Boolean validSign(String requestUrl) {
        String requestSign = this.request.getHeader("sign");
        if (StringUtils.isBlank(requestSign)) {
            return Boolean.FALSE;
        }

        Enumeration<?> pNames = this.request.getParameterNames();
        Map<String, String> params = new HashMap<>();
        while (pNames.hasMoreElements()) {
            String pName = (String)pNames.nextElement();
            String pValue = this.request.getParameter(pName);
            params.put(pName, pValue);
        }
        String checkSign = generateSign(params, requestUrl);
        System.out.println("请求的sign-->>" + requestSign);
        System.out.println("验证的sign-->>" + checkSign);
        if (requestSign.equals(checkSign)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private String generateSign(Map<String, String> params, String requestUrl) {
        StringBuilder sign = new StringBuilder();
        String[] keys = (String[])params.keySet().toArray((Object[])new String[0]);
        Arrays.sort((Object[])keys);
        for (String key : keys) {
            sign.append(key).append("=").append(params.get(key)).append("&");
        }
        sign.append("requestUrl").append("=").append(requestUrl);
        return DigestUtils.md5Hex(sign.toString());
    }


    public TokenView getTokenView() {
        String tokenStr = getHeader("x-access-token");
        if (StringUtils.isBlank(tokenStr)) {
            return null;
        }
        HashOperations<String, String, TokenView> opsForHash = this.redisTemplate.opsForHash();
        TokenView tokenView = (TokenView)opsForHash.get("x-access-token", tokenStr.split("_")[0]);
        return tokenView;
    }

    protected String getHeader(String name) {
        if (null == this.request) {
            return null;
        }
        return this.request.getHeader(name);
    }
}
